package com.asa.group;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.asa.fushu.bean.Fushu;



/**
 * 没有使用泛型对其进行扩展，仅仅在复数域
 * 群其实其本身并不需要和具体的数域相关连，任何的事物都可以构建成群
 * 
 * 这里是只能关注有限离散的
 * 里面的equle不知道有必要改为实现compareable接口的方式没有
 * @author asa
 *
 */
public class Group{
	
	
	/**
	 * 判断一个集合是否是群
	 * @param <T> 必须重新equels方法
	 * @param list	它就是从G
	 * @param asa	运算规则
	 * @param e		单位元
	 * @return
	 * 
	 * 需要满足四点	这里的*不代表特定乘法，它代表一种运算方式
	 * 	①结合律
	 * 	②存在单位元e 使得任意的a属于G， a*e=e*a = a
	 * 	③任意的a属于G，存在a的逆属于G， a*a的逆 = a的逆*a =e
	 *  ④对于任意a，b属于lis，a，b的运算依然属于lis	
	 *  
	 *  
	 *  只满足④称之为原群
	 *  只满足①④，称之为半群
	 *  
	 *  
	 * 
	 */
	public static<T> boolean isGroup(ArrayList<T> list,ObjectFunction<T> asa,T e) {
		if (list.size()==0) {
			return false;
		}
		
		list.contains(e);
		
		
		
		ArrayList<T> buffer = new ArrayList<T>();
		
		buffer.addAll(list);
		buffer.addAll(list);
		buffer.addAll(list);
		
//		System.out.println(buffer.size());
		//满足结合律否
		boolean jieHeLv = isJieHeLv(buffer,asa);
//		System.out.println("jieHeLv:"+jieHeLv);
		if (!jieHeLv) {
			return false;
		}
		
		
		
		
		if (e==null) {
			
			T hasEAndFind = isHasEAndFind(list, asa);
			if (hasEAndFind==null) {
				return false;
			}
			
			
			boolean isHasE2 = isHasE2(list, asa,hasEAndFind);
			
			if (!isHasE2) {
				return false;
			}
			

			
			
			
		}else {
			//满足②？
			boolean hasE = isHasE(list, asa, e);
//			System.out.println("hasE:"+hasE);

			if (!hasE) {
				return false;
			}
			
			
			
			
			//满足③？
			boolean hasE2 = isHasE2(list, asa, e);
//			System.out.println("hasE2:"+hasE2);

			if (!hasE2) {
				return false;

			}
			
			
			
			
			
			
		}
		
		
		
		boolean funcContaint = funcContaint(list, asa);//条件④，计算完后仍然在里面

		if (!funcContaint) {
			return false;

		}
		
		
		return true;
		
	}
	
	
	
	
	
	
	/**
	 * 找出单位元
	 * @param <T>
	 * @param list
	 * @return
	 */
	public static<T> T findE(ArrayList<T> list,ObjectFunction<T> func) {
		
		
		for (int i = 0; i < list.size(); i++) {
			T e = list.get(i);
			
			for (int j = 0; j < list.size(); j++) {//如果所有元素与它运算都是其本身
				T ele = list.get(j);
				
				if (!func.hanshu(ele, e).equals(ele)) {
					continue;
				}
				
				if (!func.hanshu(e, ele).equals(ele)) {
					continue;
				}
				
				
				
			}
			
			
			return e;
			
			
		}
		
		
		
		
		return null;
	}
	
	
	
	/**
	 * 找出零元
	 * @param <T>
	 * @param list
	 * @return
	 */
	public static<T> T findZero(ArrayList<T> list,ObjectFunction<T> func) {
		
		for (int i = 0; i < list.size(); i++) {
			T zero = list.get(i);
			
			for (int j = 0; j < list.size(); j++) {//如果所有元素与它运算都等于它
				T ele = list.get(j);
				
				if (!func.hanshu(ele, zero).equals(zero)) {
					continue;
				}
				
				if (!func.hanshu(zero, ele).equals(zero)) {
					continue;
				}
				
				
				
			}
			
			
			return zero;
			
			
		}
		
		return null;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * 半群
	 * 满足两条即可
	 * 	①结合律
	 *  ④对于任意a，b属于lis，a，b的运算依然属于lis	
	 * 即③任意的a属于G，存在a的逆属于G， a*a的逆 = a的逆*a =e，这条不需要被满足
	 * @param <T>
	 * @param list
	 * @param asa
	 * @param e
	 * @return
	 */
	public static<T> boolean isGroupSemigroup (ArrayList<T> list,ObjectFunction<T> asa) {
		if (list.size()==0) {
			return false;
		}
		
		
		ArrayList<T> buffer = new ArrayList<T>();
		
		buffer.addAll(list);
		buffer.addAll(list);
		buffer.addAll(list);
		
//		System.out.println(buffer.size());
		//满足结合律否
		boolean jieHeLv = isJieHeLv(buffer,asa);
//		System.out.println("jieHeLv:"+jieHeLv);
		if (!jieHeLv) {
			return false;
		}
		
		
		boolean funcContaint = funcContaint(list, asa);//条件④，计算完后仍然在里面

		if (!funcContaint) {
			return false;

		}
		
		
		return true;
		
	}
	
	
	/**
	 * 幺半群
	 * 它满足群的定义，除了逆元这一条不满足
	 * 即③任意的a属于G，存在a的逆属于G， a*a的逆 = a的逆*a =e，这条不需要被满足
	 * @param <T>
	 * @param list
	 * @param asa
	 * @param e
	 * @return
	 */
	public static<T> boolean isGroupMonoid(ArrayList<T> list,ObjectFunction<T> asa,T e) {
		if (list.size()==0) {
			return false;
		}
		
		list.contains(e);
		
		
		
		ArrayList<T> buffer = new ArrayList<T>();
		
		buffer.addAll(list);
		buffer.addAll(list);
		buffer.addAll(list);
		
//		System.out.println(buffer.size());
		//满足结合律否
		boolean jieHeLv = isJieHeLv(buffer,asa);
//		System.out.println("jieHeLv:"+jieHeLv);
		if (!jieHeLv) {
			return false;
		}
		
		
		
		
		if (e==null) {
			
			T hasEAndFind = isHasEAndFind(list, asa);
			if (hasEAndFind==null) {
				return false;
			}
			
			
		}else {
			//满足②？
			boolean hasE = isHasE(list, asa, e);
//			System.out.println("hasE:"+hasE);

			if (!hasE) {
				return false;
			}
			
			
		}
		
		
		
		boolean funcContaint = funcContaint(list, asa);//条件④，计算完后仍然在里面

		if (!funcContaint) {
			return false;

		}
		
		
		return true;
		
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * 判断集合是否是able群
	 * 在它是群的基础上，它满足交换律就是able群了
	 * @param <T> 必须重新equels方法
	 * @param list	它就是从G
	 * @param asa	运算规则
	 * @param e		单位元
	 * @return
	 */
	public static<T> boolean isAbleGroup(ArrayList<T> list,ObjectFunction<T> asa,T e) {
		
		
		boolean group = isGroup(list,asa,e);
		
		if (!group) {
			return false;
		}
		
		isJiaoHuanLv(list, asa);
		
		
		
		
		
		return true;
		
	}
	
	
	
	

	//子群
	
	/**
	 * 判断一个群lis是不是list的一个子群
	 * 简单点说就是，lis是由list中得元素组成，并且lis满足群得定义
	 * @param <T> 必须重新equels方法
	 * @param list
	 * @param asa 判断的子群
	 * @return
	 * 需要满足四个条件
	 * ①对于任意a，b属于lis，a，b的运算依然属于lis		
	 * ②lis包含单位元
	 * ③任意a属于lis，都有a的逆元属于lis
	 * ④list包含lis中所有元素
	 * 
	 * 
	 * 某群是某群的子群用<号表示
	 */
	public static<T> boolean ishgroup(ArrayList<T> list,ArrayList<T> lis,ObjectFunction<T> asa,T e){
		
		
		boolean containtAll = containtAll(list, lis);//④
		if (!containtAll) {
			return false;
		}
		
		
		boolean hasE2 = isHasE2(list, asa, e);
		
		if (!hasE2) {//③
			return false;
		}
		
		funcContaint(list, asa);//①
		
		return false;
	}
	
	
	
	
	
	/**
	 * 判断两个群是否满足f的同态映射
	 * 
	 * 同态/群同态		群的同态映射，这才是完整叫法，是对群与群的关系的描述
	 * asa 和 asb是两个群
	 * f是asa到asb得一个映射，如果这个映射是同态映射
	 * 那么，就有asa通过f映射到asb
	 * 并可以推出任意的a和b属于asa有 f(a*b) = f(a)*f(b) 		*代表的是运算，不局限与乘法
	 * 
	 * 注意：同态映射不一定是满射、双射、单射，这些情况需要另外讨论，但asa上所有值必须能通过f映射到asb
	 * 
	 * @param <T>T和S这个两个泛型可以相同，也可以不同
	 * @param <S>T和S这个两个泛型可以相同，也可以不同
	 * @param list1	asa群
	 * @param list2 asb群
	 * @param func1	asa的运算法则
	 * @param func2	asb的运算法则
	 * @param f	asa到asb的映射法则
	 * @return
	 * 
	 * 性质：
	 * 		asa中的单位元对应asb中的单位元
	 * 		asa中任意元素a的逆对应 a对应asb中元素的逆
	 * 			任意 a属于asa，有 f(a的逆）= f(a)的逆
	 * 		asa可以是asb的子群，可以满足这个效果
	 * 		自身到自身可以满足群同态
	 * 		一般实数线性群（乘法），对应实数（乘法，去0了）群满足同态
	 * 
	 * 
	 * 		如果：
	 * 			①f满射
	 * 				asb都可以找到的asa上的元素
	 * 				kernel等于asa的某些元素组成的集合，并且这个集合必然包含单位元
	 * 				
	 * 
	 * 			②f单射
	 * 				asa都可以找到唯一的asb上的元素
	 * 				kernel等于asa的单位元
	 * 				
	 * 
	 * 			③f双射
	 * 				asa和asb上元素一一对应
	 * 				kernel等于asa的单位元
	 * 			结论可逆
	 * 
	 * 同态用
	 * 
	 */
	public static<T,S> boolean isHomomorphism(ArrayList<T> list1,ArrayList<S> list2,
			ObjectFunction<T> func1,ObjectFunction<S> func2,ObjectFunction2<T,S> f) {
		
		List<T> asa = new ArrayList<T>();
		asa.addAll(list1);
		asa.addAll(list1);
		
		List<int[]> combination = Shuffle.Combination(asa.size(), 2);
		
		for (int i = 0; i < combination.size(); i++) {
			int[] js = combination.get(i);
			
			//判断是否满足f(a*b) = f(a)*f(b)
			T t1 = asa.get(js[0]);
			T t2 = asa.get(js[1]);
			
			S s1 = f.hanshu(t1);
			S s2 = f.hanshu(t2);
			
			

			T hanshu1 = func1.hanshu(t1, t2);
			S s3 = f.hanshu(hanshu1);
			S hanshuS1 = func2.hanshu(s1, s2);
			
			if (!s3.equals(hanshuS1)) {
				return false;
			}
			
			//排列组合默认就是要满足两种情况
			T hanshu2 = func1.hanshu(t2, t1);
			S s4 = f.hanshu(hanshu2);
			S hanshuS2 = func2.hanshu(s1, s2);
				

			if (!s4.equals(hanshuS2)) {
				return false;
			}
			
			if (list2.contains(s1)&&list2.contains(s2)&&list2.contains(s3)&&list2.contains(s4)
					&&list2.contains(hanshuS1)&&list2.contains(hanshuS2)) {
				continue;
			}else {
				return false;
			}
			
			
			
		}
		
		
		
		
		
		return true;
	}
	
	
	
	
	
	/**
	 * 核与像的概念
	 * 核kernel
	 * 像image
	 * 
	 * 如果asa与asb都是群，并且关于f同态的
	 * 那么，ker(f) = {存在a属于asa有，f(a)=asb的e} 或者写成 ker(f) = {存在a属于asa有，其中f(a)=e`}	,翻译成通俗语言是，f的核为asa到asb的单位元的映射关系
	 * 这里关于核其实有个隐含前提，就是asa通f映射到asb上的单位元e，可能存在对多个asa的元素都能通过f映射到asb上的e，这部分关系都是核，这个是从asa到asb多对一的关系
	 * ker(f)是个集合，而它上面的元素都来自于asa
	 * 
	 * 
	 * Im(f) = {f(a),其中a属于asa}	，翻译成通俗语言是，从asa映射到asb关系都是像的关系，映射到的asb的元素都是像
	 * Im(f)是个集合，它里面的元素都来自asb
	 * 
	 * 核与像是通过对于f映射的这种关系的再次划分，通过这种划分，提取出对应asa和asb里面的元素，生成两个不同的集合
	 * 是一种衍生的关系
	 * 
	 * 
	 * 
	 * 可以知道的性质
	 * 		asa上的满足核关系的元素所构成的集合是一个群，并且是asa的子群（可以由同态的定义+群的定义来矛盾推出）
	 * 		asb上满足像关系的元素所构成的集合是一个群，并且是asb的子群
	 * 		asa上的满足核关系的元素所构成的集合是一个群，理所当然的单位元是asa的单位元
	 * 
	 * 
	 * 
	 * 可以验证， ker(f)  是 asa 的子群。
	 * 可以验证， Im(f)  是 asb 的子群。
	 * 
	 * 
	 */
	
	/**
	 * 找出核，需要群list1和群list2确定是关于f的同态关系
	 * @param <T>
	 * @param <S>
	 * @param list1
	 * @param list2
	 * @param func1
	 * @param func2
	 * @param f
	 * @param et
	 * @param es
	 */
	public static<T,S> ArrayList<T> findKernel(ArrayList<T> list1,ArrayList<S> list2,
			ObjectFunction<T> func1,ObjectFunction<S> func2,ObjectFunction2<T,S> f,T et,S es) {
		
		ArrayList<T> kernel = new ArrayList<T>();
		for (int i = 0; i < list1.size(); i++) {
			
			T t = list1.get(i);
			S hanshu = f.hanshu(t);
			if (hanshu.equals(es)) {
				kernel.add(t);
			}
			
		}
				
		
		return kernel;
	}
	
	
	/**
	 * 判断两个集合是否是满射
	 * 每个list2中的元素必须有list1中的元素对应
	 * @param <T>
	 * @param <S>
	 * @param list1
	 * @param list2
	 * @param f
	 * @return
	 */
	public static<T,S> boolean ismangshe(ArrayList<T> list1,ArrayList<S> list2,ObjectFunction2<T,S> f) {
		
		
		for (int i = 0; i < list2.size(); i++) {
			S s = list2.get(i);
			List<T> hanshuNi = f.hanshuNi(s);
			
			if (hanshuNi.size()==0) {
				return false;
			}
			
			boolean hasone = false;
			for (int j = 0; j < hanshuNi.size(); j++) {
				T t = hanshuNi.get(j);
				
				boolean contains = list1.contains(t);
				if (contains) {
					hasone = true;
					break;
				}
				
			}
			if (!hasone) {
				return false;
			}
			
			
		}
		
		return false;
	}
	
	/**
	 * 判断两个集合是否是单射
	 * list1的每个元素必须有唯一的list2中的元素相对应
	 * 
	 * @param <T>
	 * @param <S>
	 * @param list1
	 * @param list2
	 * @param f
	 * @return
	 */
	public static<T,S> boolean isdangshe(ArrayList<T> list1,ArrayList<S> list2,ObjectFunction2<T,S> f) {
		
		List<S> buffer = new ArrayList<>();
		for (int i = 0; i < list1.size(); i++) {
			T t = list1.get(i);
			S hanshu = f.hanshu(t);
			
			boolean contains = list2.contains(hanshu);
			if (!contains) {
				return false;
			}
			if (!buffer.contains(hanshu)) {
				return false;
			}
			buffer.add(hanshu);

			
		}
		return false;
	}
	
	
	/**
	 * 判断两个集合是否是双射
	 * 既是满射又是单射
	 * @param <T>
	 * @param <S>
	 * @param list1
	 * @param list2
	 * @param f
	 * @return
	 */
	public static<T,S> boolean isshuangshe(ArrayList<T> list1,ArrayList<S> list2,ObjectFunction2<T,S> f) {
		
		boolean ismangshe = ismangshe(list1, list2, f);
		if (!ismangshe) {
			return false;
		}
		
		boolean isdangshe = isdangshe(list1, list2, f);
		
		if (!isdangshe) {
			return false;
		}
		
		return true;
	}
	
	
	
	
	
	
	
	
	
	/**
	 * 判断是不是核
	 * 如果asa与asb都是群，并且关于f同态的
	 * 那么，ker(f) = {存在a属于asa有，f(a)=asb的e} 或者写成 ker(f) = {存在a属于asa有，其中f(a)=e`}	,翻译成通俗语言是，f的核为asa到asb的单位元的映射关系
	 * 这里关于核其实有个隐含前提，就是asa通f映射到asb上的单位元e，可能存在对多个asa的元素都能通过f映射到asb上的e，这部分关系都是核，这个是从asa到asb多对一的关系
	 * ker(f)是个集合，而它上面的元素都来自于asa
	 * @param <T>
	 * @param <S>
	 * @param list1
	 * @param list2
	 * @param func1
	 * @param func2
	 * @param f
	 * @param et
	 * @param es
	 * @param kernel	核
	 * @return
	 */
	public static<T,S> boolean isKernel(ArrayList<T> list1,ArrayList<S> list2,
			ObjectFunction<T> func1,ObjectFunction<S> func2,ObjectFunction2<T,S> f,T et,S es,ArrayList<T> kernel) {
		
		boolean group = isGroup(kernel, func1, et);
		if (!group) {
			return false;
		}
		
		
		ArrayList<T> findKernel = findKernel(list1, list2, func1, func2, f, et, es);
		boolean listsIsEquel = isEquel(kernel, findKernel);
		
		if (!listsIsEquel) {
			return false;
		}
		
		return true;
	}





	/**
	 * 判断两个集合中的元素是否都有
	 * @param <T>
	 * @param list1
	 * @param list2
	 * @return
	 */
	public static <T> boolean isEquel(ArrayList<T> list1, ArrayList<T> list2) {
		if (list1.size()!=list2.size()) {
			return false;
		}
		
		for (int i = 0; i < list1.size(); i++) {
			
			T t = list1.get(i);
			boolean contains = list2.contains(t);
			if (!contains) {
				return false;
			}
			
		}
		for (int i = 0; i < list2.size(); i++) {//其实如果两个集合的元素去重了，这个二次判断就没必要了
			
			T t = list2.get(i);
			boolean contains = list1.contains(t);
			if (!contains) {
				return false;
			}
			
		}
		
		
		
		return true;
	}
	
	
	
	
	
	/**
	 * 找出像，需要群list1和群list2确定是关于f的同态关系
	 * @param <T>
	 * @param <S>
	 * @param list1
	 * @param list2
	 * @param func1
	 * @param func2
	 * @param f
	 * @param et
	 * @param es
	 * @return
	 */
	public static<T,S> ArrayList<S> findImage(ArrayList<T> list1,ArrayList<S> list2,
			ObjectFunction<T> func1,ObjectFunction<S> func2,ObjectFunction2<T,S> f,T et,S es) {
		
		ArrayList<S> image = new ArrayList<S>();
		for (int i = 0; i < list1.size(); i++) {
			
			T t = list1.get(i);
			S hanshu = f.hanshu(t);
			
			boolean contains = list2.contains(hanshu);
			if (contains) {//必须要加上它
				image.add(hanshu);
			}
			
		}
		
		return image;
	}
	
	/**
	 * 判断是不是像
	 * @param <T>
	 * @param <S>
	 * @param list1
	 * @param list2
	 * @param func1
	 * @param func2
	 * @param f
	 * @param et
	 * @param es
	 * @param image	像
	 * @return
	 */
	public static<T,S> boolean isImage(ArrayList<T> list1,ArrayList<S> list2,
			ObjectFunction<T> func1,ObjectFunction<S> func2,ObjectFunction2<T,S> f,T et,S es,ArrayList<S> image) {
		
		boolean group = isGroup(image, func2, es);
		if (!group) {
			return false;
		}
		ArrayList<S> findImage = findImage(list1, list2, func1, func2, f, et, es);
		
		if (findImage.size()!=image.size()) {
			return false;
		}
		
		for (int i = 0; i < image.size(); i++) {
			
			S t = image.get(i);
			boolean contains = findImage.contains(t);
			if (!contains) {
				return false;
			}
			
		}
		
		
		
		
		
		
		return true;
	}
	
	
	
	
	/**
	 * 判断是否同构
	 * 同构
	 * 定义：
	 * ①f bij 双射的意思
	 * ②f的asa到asb是同态映射
	 * ③f的逆，asb到asa是同态映射	其实只要满足前两者，这个就成立了，为了好看好理解点
	 * 
	 * 同构≃这个符号表示
	 * 
	 * 
	 * 同构提供了一些性质
	 * 		f是asa到asb的同构，也是asb到asc的同构，那么g*f也是asa到asc的一个同构（传递性）
	 * 		f是asa到asb的同构，那么asa和asb的元素数一致
	 * 		f是asa到asb的同构，如何H<asa 充分必要条件是 f(H)<asb
	 * 		
	 * 
	 * 
	 */
	public static<T,S> boolean isomorphism(ArrayList<T> list1,ArrayList<S> list2,
			ObjectFunction<T> func1,ObjectFunction<S> func2,ObjectFunction2<T,S> f) {
		
		
		boolean isshuangshe = isshuangshe(list1, list2, f);

		if (!isshuangshe) {
			return false;
		}
		
		boolean homomorphism = isHomomorphism(list1, list2, func1, func2, f);
		
		if (!homomorphism) {
			return false;
		}
		
		return true;
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * 找到一个群的它的所有子群
	 * 有点难，感觉可以得出很多很多个解
	 * @param <T> 必须重新equels方法
	 * @param list
	 * @return
	 */
	public static<T> List<List<T>> hgroup(ArrayList<T> list,T e){
		
		
		
		
		
		return null;
	}
	
	
	/**
	 * 判断集合中得值计算后是否都还在集合中
	 * 有一个疑问，元素自己和自己得运算要不要包含在里面（我得做法是要得）
	 * @param <T>
	 * @param list
	 * @param asa
	 * @return
	 */
	public static<T> boolean funcContaint(ArrayList<T> list,ObjectFunction<T> asa){
		
		ArrayList<T> buffer = new ArrayList<T>();
		buffer.addAll(list);
		buffer.addAll(list);

		
		List<int[]> combination = Shuffle.Combination(buffer.size(), 2);
		
		
		for (int i = 0; i < combination.size(); i++) {
			int[] js = combination.get(i);
			
			T t1 = buffer.get(js[0]);
			T t2 = buffer.get(js[1]);

			T hanshu1 = asa.hanshu(t1, t2);
			boolean contains = list.contains(hanshu1);
			if (!contains) {
//				System.out.println(t1 +"  contains "+hanshu1);
				
				return false;
			}
			
			
			
			T hanshu2 = asa.hanshu(t2, t1);
			boolean contains2 = list.contains(hanshu2);
			
			if (!contains2) {
//				System.out.println(t1 +"  contains2  "+hanshu1);

				return false;
			}
			
			
//			System.out.println(i);
			
		}
		
		
		
		
		
		
		
		
		return true;
		
	}

	
	
	
	
	
	
	
	
	/**
	 * 判断是否在是包含关系
	 * @param <T> 必须重新equels方法
	 * asa都在list中
	 * @param list
	 * @param asa
	 * @return
	 */
	public static<T> boolean containtAll(ArrayList<T> list,ArrayList<T> asa){
		
		if (asa.size()>list.size()) {
			return false;
		}
		
		
		for (int i = 0; i < asa.size(); i++) {
			
			boolean contains = list.contains(asa.get(i));
			if (!contains) {
				return false;
			}
		}
		
		
		
		
		return true;
		
	}
	
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * 满足结合律否
	 * @param <T> 必须重新equels方法
	 * @param list
	 * @param asa
	 * @return
	 */
	public static<T> boolean isJieHeLv(ArrayList<T> list,ObjectFunction<T> asa) {
		int size = list.size();
		
		List<int[]> combination = Shuffle.Combination(size, 3);
		
		
		for (int i = 0; i < combination.size(); i++) {
			int[] js = combination.get(i);
			
			
			List<int[]> permutation = Shuffle.Permutation(js);
			
			for (int j = 0; j < permutation.size(); j++) {
				int[] ks = permutation.get(j);
				//看每一个情况是否满足结合律
				
				ArrayList<T> detail = new ArrayList<>();
				for (int k = 0; k < ks.length; k++) {
					detail.add(list.get(ks[k]));
				}
				
				boolean jieHeLvDetail = isJieHeLvDetail(detail,asa);
				
				if (!jieHeLvDetail) {
					return false;
				}
				
			}
			
			
		}
		
		
		return true;
	}
	
	
	
	
	/**
	 * 结合律细节
	 * @param <T> 必须重新equels方法
	 * @param detail
	 * @param asa
	 * @return
	 */
	public static<T> boolean isJieHeLvDetail(ArrayList<T> detail,ObjectFunction<T> asa) {
		T fushu1 = detail.get(0);
		T fushu2 = detail.get(1);
		T fushu3 = detail.get(2);

		T hanshu1 = asa.hanshu(fushu1, fushu2);
		T hanshu2 = asa.hanshu(hanshu1, fushu3);
		
		
		T hanshu3 = asa.hanshu(fushu2, fushu3);
		T hanshu4 = asa.hanshu(fushu1, hanshu3);

		
		
		return hanshu2.equals(hanshu4);
	}
	
	
	
	
	
	
	
	/**
	 * 满足交换律
	 * @param <T> 必须重新equels方法
	 * @param list
	 * @param asa
	 * @return
	 */
	public static<T> boolean isJiaoHuanLv(ArrayList<T> list,ObjectFunction<T> asa) {
		if (list.size()==1) {
			return true;
		}else if (list.size()==0) {
			return false;
		}
		
		int size = list.size();
		
		List<int[]> combination = Shuffle.Combination(size, 2);
		
		for (int i = 0; i < combination.size(); i++) {
			int[] js = combination.get(i);
			ArrayList<T> detail = new ArrayList<>();

			for (int j = 0; j < js.length; j++) {
				detail.add(list.get(js[j]));
			}
			
			boolean jiaoHuanLvDetail = isJiaoHuanLvDetail(detail, asa);
			if (!jiaoHuanLvDetail) {
				return false;
			}
			
			
			
		}
		
		
		
		
		
		return true;
	}
	
	
	/**
	 * 交换律细节
	 * @param <T> 必须重新equels方法
	 * @param detail
	 * @param asa
	 * @return
	 */
	public static<T> boolean isJiaoHuanLvDetail(ArrayList<T> detail,ObjectFunction<T> asa) {
		T fushu = detail.get(0);
		T fushu2 = detail.get(1);
		
		T hanshu = asa.hanshu(fushu, fushu2);
		T hanshu2 = asa.hanshu(fushu2, fushu);
		
		
		return hanshu.equals(hanshu2);
	}

	
	
	
	/**
	 * 存在单位元e 使得任意的a属于G， a*e=e*a = a
	 * @param <T> 必须重新equels方法
	 * @return
	 */
	public static<T> boolean isHasE(ArrayList<T> list,ObjectFunction<T> asa,T e) {
		
		
		for (int i = 0; i < list.size(); i++) {
			
			T fushu = list.get(i);
			
			T hanshu = asa.hanshu(fushu, e);
			
			if (!hanshu.equals(fushu)) {
				return false;
			}
			
			
			T hanshu2 = asa.hanshu(e, fushu);
			
			if (!hanshu.equals(hanshu2)) {
				return false;
			}
			
		}
		
		return true;
	}
	
	/**
	 * 存在单位元e 使得任意的a属于G， a*e=e*a = a
	 * 如果我们不知道e是什么
	 * @param <T> 必须重新equels方法
	 * @param list
	 * @param asa
	 * @return
	 */
	public static<T> T isHasEAndFind(ArrayList<T> list,ObjectFunction<T> asa) {
		
		
		
		return null;
	}
	
	
	
	/**
	 * 任意的a属于G，存在a的逆属于G， a*a的逆 = a的逆*a =e
	 * @param <T> 必须重新equels方法
	 * @param list
	 * @param asa
	 * @param e
	 * @return
	 */
	public static<T> boolean isHasE2(ArrayList<T> list,ObjectFunction<T> asa,T e) {
		
		
		
		for (int i = 0; i < list.size(); i++) {
			boolean isgetit = false;
			T fushu = list.get(i);
			
			if (fushu.equals(e)) {
				continue;
			}
			
			for (int j = 0; j < list.size(); j++) {//已经考虑自己是自己的逆元的情况了
				T fushu2 = list.get(j);
				if (fushu2.equals(e)) {
					continue;
				}
				
				T hanshu = asa.hanshu(fushu, fushu2);
				
				if (hanshu.equals(e)) {
					
					T hanshu2 = asa.hanshu(fushu2, fushu);
					
					if (hanshu2.equals(e)) {
						isgetit = true;
						break;
					}
					
				}
				
				
				
				
				
				
				
				
			}
			
			
			if (!isgetit) {
				return false;
			}
			
			
			
		}
		
		
		
		
		return true;
	}
	
	/**
	 * 任意的a属于G，存在a的逆属于G， a*a的逆 = a的逆*a =e
	 * 如果我们不知道e是什么
	 * @param <T> 必须重新equels方法
	 * @param list
	 * @param asa
	 * @return
	 */
	public static<T> T isHasE2AndFind(ArrayList<T> list,ObjectFunction<T> asa) {
		
		
		
		return null;
	}
	
	
	
	
	public static void main(String[] args) {
		
		
		
		ArrayList<Fushu> src = new ArrayList<Fushu>();
		
		src.add(new Fushu(1, 0));
		src.add(new Fushu(-1, 0));
//		src.add(new Fushu(0, 0));

//		boolean group = isGroup(src , new RFunction() {
//			
//			@Override
//			public Fushu hanshu(Fushu a, Fushu b) {
//				// TODO Auto-generated method stub
//				return a.mul(b);
//			}
//		}, new Fushu(0, 0));
//		
//		
//		System.out.println("result:"+group);
		
		
		
		boolean ableGroup = isAbleGroup(src, new ObjectFunction<Fushu>() {
			
			@Override
			public Fushu hanshu(Fushu a, Fushu b) {
				// TODO Auto-generated method stub
				return a.mul(b);
			}
		}, new Fushu(1, 0));
		
		System.out.println("ableGroup result:"+ableGroup);

		
		
		boolean funcContaint = funcContaint(src, new ObjectFunction<Fushu>() {	
			@Override
			public Fushu hanshu(Fushu a, Fushu b) {
				// TODO Auto-generated method stub
				return a.mul(b);
			}
		});
		
		System.out.println("funcContaint:"+funcContaint);
		
		
		
		
		
		
	}
	
	
	
	//确定集合已经是一个群了，那么它默认有一些性质
	//逆元的唯一性
	//单位元唯一性
	//某个元素的逆元是一定存在的

}
